<script lang="ts" setup>
import { message } from 'ant-design-vue';

import type { IBaseRequest, IPageRequest, ISearchParams } from '@/types/request';
import type { ColumnsType, TablePaginationConfig } from 'ant-design-vue/es/table';
import type { Transform, PaginationConfig, TransformValueOf } from '@/types/table-transform';
import { uploadImage } from '@/api/upload';

const { expandColumns, realDataSource, searchParams, notDel, notGmt, ...methods } = defineProps<{
  expandColumns: ColumnsType
  realDataSource: Transform<any>[]
  searchParams: ISearchParams
  notDel?: boolean
  custom?: boolean
  notGmt?: boolean
  onRequest: () => Promise<IPageRequest<any>>
  onDelete?: (value: string) => Promise<IBaseRequest<any>>
  onUpdate?: (value: TransformValueOf<Transform<any>>) => Promise<IBaseRequest<any>>
}>()

// 默认表的列格式
const defaultColums: ColumnsType = [
  !notGmt ? {
    title: '创建时间',
    dataIndex: 'gmt_create',
    key: 'gmt_create',
    notShowInput: true,
    align: 'center',
    width: 120
  } : {},
  methods?.onUpdate ? {
    title: '操作',
    key: 'operation',
    width: 180,
    align: 'center',
    fixed: 'right'
  } : {},
]

// 分页器逻辑
const pagination = ref<PaginationConfig>({
  title: '',
  current: 0,
  total: 0,
  pageSize: 0,
  onChange: async (page) => {
    searchParams.page = page
    await handleRequest()
  },
})

// 监听搜索内容改变分页器的数据
watch(() => searchParams, () => {
  pagination.value.current = searchParams.page
  pagination.value.total = searchParams.total
  pagination.value.pageSize = searchParams.size
}, { deep: true })


// 将 有原始值和修改后的值 数据更改为只有修改后的值
const dataSource = computed(() => {
  return realDataSource.map(item => Object.entries(item).reduce((acc, [key, value]) => {
    return {
      ...acc,
      [key]: value.text
    }
  }, {}))
})

// 汇总表格的列格式
const columns = computed<ColumnsType>(() => {
  return [
    {
      title: 'ID',
      dataIndex: 'id',
      key: 'id',
      notShowInput: true,
      width: 100,
      align: 'center',
      fixed: 'left'
    },
    ...expandColumns,
    ...defaultColums.filter(item => item.title),
  ]
})


// 数据改变时表格加载的动画
let isLoading = ref(false)
async function request(callback: () => Promise<void>) {
  isLoading.value = true
  try {
    await callback()
  } catch (error: any) {
    message.error(error.message || error)
  } finally {
    isLoading.value = false
  }
}

// 执行父组件传入的搜索方法
async function handleRequest() {
  await request(async () => {
    const { data } = await methods.onRequest()
    searchParams.total = data.total_record
  })
}

// 删除方法
async function handleDelete(index: number) {
  const record = realDataSource[index]
  if (record.del.value) {
    message.error('此项目已经被删除')
    return
  }

  await request(async () => {
    if (!methods.onDelete) {
      return
    }
    const { code } = await methods.onDelete(String(record.id.value))
    if (code === 0) {
      message.success('删除成功')
      await handleRequest()
    }
  })
}

let editingIndex = ref(-1)
let editableData = ref<Transform<any>>()
async function handleEditOrSave(index: number) {
  // 保存逻辑
  if (editingIndex.value === index) {
    // 将有原始值和修改后的值 数据更改为只有原始的值
    const toUploadData = Object.entries(editableData.value!).map(([key, value]) => {
      return {
        [key]: value.value
      }
    }).reduce((acc, cur) => {
      return {
        ...acc,
        ...cur
      }
    }, {}) as TransformValueOf<typeof realDataSource[0]>

    await request(async () => {
      if (!methods?.onUpdate) return
      const { code } = await methods.onUpdate(toUploadData)
      if (code === 0) {
        editingIndex.value = -1
        message.success('修改成功')
        await handleRequest()
      }
    })
  } else {
    // 编辑逻辑
    editingIndex.value = index
    editableData.value = realDataSource[index]
  }
}

// 取消方法
function handleCancel() {
  editingIndex.value = -1
  editableData.value = undefined
}

const uploadImg = ref<HTMLInputElement>()

// 点击上传图片
function handleUploadImageUpload() {
  uploadImg.value!.click()
}

let imageUploadLoading = ref(false)
//更新图片
async function handleUploadImageChange(index: number, columnKey: string, e: Event) {
  const target = e.target as HTMLInputElement
  const file = target.files?.[0]
  if (file) {
    imageUploadLoading.value = true
    const { code, data } = await uploadImage(file).finally(() => imageUploadLoading.value = false)
    if (code === 0) {
      realDataSource[index][columnKey].value = data
    } else {
      message.error('上传失败，请重试')
    }
  }
}

onMounted(async () => await handleRequest())
</script>

<template>
  <div>
    <a-table :pagination="pagination" :columns="columns" :data-source="dataSource" :loading="isLoading">
      <template #bodyCell="{ column, record, index }">

        <!-- 输入框的列 -->
        <template v-if="editingIndex === index && column.key !== 'operation' && !column.notShowInput">
          <a-input v-model:value="editableData![column.key as any].value" />
        </template>
        <!-- 图片的列 -->
        <template v-if="column.showImage">
          <div v-if="editingIndex === index" cursor-pointer @click="handleUploadImageUpload">
            <input type="file" hidden ref="uploadImg" @change="handleUploadImageChange(index, column.key, $event)" />
            <div relative w-full h-full>
              <img :src="(editableData![column.key].value)">
              <div absolute top="0" left="0" w="full" h="full" style="background-color: rgba(0, 0, 0, 0.5);"
                flex="~ center">
                <loading-outlined v-show="imageUploadLoading" class="c-white! text-5" />
                <plus-outlined v-show="!imageUploadLoading" class="c-white! text-5" />
              </div>
            </div>
          </div>
          <img :src="record[column.key]" v-else />
        </template>
        <!-- 插槽内容 -->
        <template v-if="custom">
          <slot :index="index" :record="record" :column="column" :editableData="editableData"
            :editState="editingIndex === index" />
        </template>
        <!-- 操作的列 -->
        <template v-if="column.key === 'operation' && onUpdate">
          <a-button type="primary" mr-1 @click="handleEditOrSave(index)"
            :disabled="imageUploadLoading && editingIndex === index" style="background-color:#1677ff">
            {{ editingIndex === index ? '保存' : '编辑' }}
          </a-button>

          <a-popconfirm title="确定要删除吗？" ok-text="确定" cancel-text="取消" @confirm="handleDelete(index)"
            v-if="editingIndex !== index && onDelete">
            <a-button type="primary" danger :disabled="imageUploadLoading && editingIndex === index">删除</a-button>
          </a-popconfirm>
          <a-button @click="handleCancel" :disabled="imageUploadLoading && editingIndex === index"
            v-else-if="editingIndex === index">取消</a-button>
        </template>
      </template>
    </a-table>
   
  </div>
</template>

<style>
.ant-table-thead>tr>th {
  text-align: center;
}

.ant-table-tbody>tr>td {
  text-align: center;
}

.truncate-cell {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>
